#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<string>
#include<cstring>
#include<cstdlib>
#include<sys/wait.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<fstream>
 
using namespace std;

int main()
{
  //申请套接字
  int listen_sock=socket(AF_INET,SOCK_STREAM,0);
  if(listen_sock<0)
  {
    cout<<"creat sock fail"<<endl;
    return 1;
  }

  //绑定套接字和ip
  
  struct sockaddr_in local;
  memset(&local,0,sizeof(local));
  local.sin_family=AF_INET;
  local.sin_port=htons(8081);
  local.sin_addr.s_addr=INADDR_ANY;
  
  int flag=1;
  setsockopt(listen_sock,SOL_SOCKET,SO_REUSEPORT,&flag,sizeof(flag));
  if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0)
  {
    cout<<"bind error"<<endl;
    return 2;
  }

  //开始监听
  if(listen(listen_sock,5)<0)
  {
    cout<<"listen error"<<endl;
    return 3;
  }
  //循环接收数据
  struct sockaddr_in peer;
  for(;;)
  {
    socklen_t len=sizeof(peer);
    int sock=accept(listen_sock,(struct sockaddr*)&peer,&len);
    if(sock<0)
    {
        cout<<"accept error"<<endl;
        continue;
    }
    //采用孙子进程服务
    if(fork()==0)
    {
      if(fork()>0)
      {
        //让爸爸退出
        exit(-1);
      }
      close(listen_sock);
      //孙子进程服务
      //read httprequest
     char buffer[1024];
     recv(sock,buffer,sizeof(buffer),0);
    cout<<"################################"<<endl;
    cout<<buffer<<endl;
    cout<<"################################"<<endl; 
    
    #define PAGE "index.html"
    ifstream in(PAGE);
    if(in.is_open())
    {
      in.seekg(0,ios::end);
      size_t len=in.tellg();
      in.seekg(0,ios::beg);
      char *file=new char[len];
      in.read(file,len);
      in.close();
      //报头 ip地址  链接信息  转态
      string status_line="http/1.1 200 OK\n";
      //string status_line="https/1.1 307 Temporary Redirect\n";
      string response_header="content_length:"+to_string(len);
      response_header+="\n";
     // response_header+="location:www.baidu.com\n";
        response_header += "Set-Cookie: abcdefg12345;\n";
                std::string blank="\n";

                send(sock, status_line.c_str(), status_line.size(), 0);
                send(sock, response_header.c_str(), response_header.size(), 0);
                send(sock, blank.c_str(), blank.size(),0);

                send(sock, file, len, 0);

                delete[] file;
    }



    close(sock);
    exit(0);
    }
  close(sock);
  waitpid(-1,nullptr,0);
  }
  return 0;
}
